package biz.datalk.industrialland.common.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * @author tarofang@163.com
 * @date 2023-05-12
 */
@Slf4j
@Component
public class RedisLockWaitUtil {

    private final RedisLock redisLock;

    @Autowired
    public RedisLockWaitUtil(RedisLock redisLock) {
        this.redisLock = redisLock;
    }

    public <T> T lockWait(String lockKey, String lockVal, RedisLockWaitHelper<T> helper) {
        return this.lockWait(lockKey, lockVal, 10L, TimeUnit.SECONDS, 10, helper);
    }

    public <T> T lockWait(String lockKey, String lockVal, long expire, TimeUnit timeUnit, int count, RedisLockWaitHelper<T> helper) {
        int i = 0, tmpCount = Math.max(count, 10);
        T unifyResult = null;
        try {
            while (i < tmpCount) {
                boolean tryLock = redisLock.tryLock(lockKey, lockVal, expire, timeUnit);
                if (tryLock) {
                    unifyResult = helper.lockSuccess();
                    break;
                }
                helper.lockFail();
                try {
                    Thread.sleep(900);
                } catch (Exception ex) {
                    log.error("{}", ex.getMessage(), ex);
                }
                i++;
            }
        } finally {
            redisLock.releaseLock(lockKey, lockVal);
        }
        return unifyResult;
    }

    public interface RedisLockWaitHelper<T> {
        T lockSuccess();

        void lockFail();
    }

}
